import axios, { Method, AxiosError } from 'axios'
class Loading {
  private count = 0
  show() {
    if (this.count == 0) {
      this.doShow()
    }
    this.count++
  }
  private doShow() {
    console.log('打开loading')
  }
  private doHide() {
    console.log('关闭loading')
  }
  hide() {
    this.count--
    if (this.count == 0) {
      this.doHide()
    }
    if (this.count < 0) {
      this.count = 0
    }
  }
}
function showMessage(e: AxiosError) {
  console.error('错误', e)
}
let ctx: any = null
function format(str: string, ctx: any) {
  let result = str.match(/\{[^\}]*\}/g)
  if (result) {
    for (let r of result) {
      let key = r.replace(/[\{\}]/g, '')
      let val = Reflect.get(ctx, key)
      if (val) {
        str = str.replace(new RegExp(r, 'g'), val)
      }
    }
  }
  return str
}
export function url(u: string, { format: fo, pre }: { format: boolean; pre: boolean } = { format: true, pre: true }) {
  if (fo) {
    if (pre) {
      u = `/{version}/{base}/${u}`
    }
    u = format(u, ctx)
    if (u.includes('://')) {
      let [protocal, path] = u.split('://')
      u = [protocal, path.replace(/\/\//g, '/')].join('://')
    } else {
      u = u.replace(/\/\//g, '/')
    }
  }
  return function (target: any, proName: string, descriptor: PropertyDescriptor) {
    if (descriptor) {
      let oldFunc = descriptor.value
      function newFunc(this: { url: string }, ...args: any[]) {
        this.url = u
        return oldFunc.call(this, ...args)
      }
      descriptor.value = newFunc
      return
    }
    throw new Error('url注解必须用在方法上。')
  }
}

class Request {
  loading: Loading = null
  private setContext(ctx1: any) {
    ctx = ctx1
  }
  init({ ctx }: { ctx: any }) {
    this.setContext(ctx)
    this.loading = new Loading()
  }
}

export const req = new Request()

export class BaseRequest {
  /**
   * 这个url就标记一下， 有一个url
   */
  protected url: string
  protected async doPost(data: any) {
    return this.doOriginal('post', data)
  }
  protected async doGet(data: any) {
    return this.doOriginal('get', data)
  }
  protected async doOriginal(method: Method, data?: any): Promise<any> {
    const loading = req.loading
    try {
      loading.show()
      let p =
        method.toLowerCase() == 'get'
          ? axios.get(this.url, {
              params: data,
            })
          : axios.post(this.url, data, {})
      const data_1 = await p
      loading.hide()
      return data_1
    } catch (error) {
      loading.hide()
      showMessage(error as AxiosError)
    }
  }
}
